package com.example.cacular;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.ViewPortHandler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    int _id=1;
    private LineChart line;
    Button bt_add_point;
    Button bt_delete;
    Button bt_fit;
    EditText et_x;
    EditText et_y;
    TextView tv_show_data;
    TextView tv_show_point_x;
    TextView tv_show_point_y;
    List<Entry> list=new ArrayList<Entry>();
    ArrayList<ILineDataSet> dataSets=new ArrayList<>();
    int max_x=100;
    int min_x=0;
    int max_y=100;
    int min_y=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        find_id();
        draw();
        set_on();
    }

    /*
    赋值控件
     */
    public void find_id(){
        et_x=findViewById(R.id.et_x);
        et_y=findViewById(R.id.et_y);
        bt_add_point=findViewById(R.id.bt_add_point);
        bt_delete=findViewById(R.id.bt_delete);
        tv_show_data=findViewById(R.id.tv_show_data);
        bt_fit=findViewById(R.id.bt_fit);
        tv_show_point_x =findViewById(R.id.tv_show_point_x);
        tv_show_point_y=findViewById(R.id.tv_show_point_y);
    }
    /*
    绘图函数
     */
    public void draw(){
        list.add(new Entry(0,0));//先绘制一个空表防止报错
        //绘图之前先将数据进行排序
        sort();
        line=findViewById(R.id.lc_comeback);
        LineDataSet lineDataSet=new LineDataSet(list,"数据点");
        dataSets.add(lineDataSet);
        LineData lineData=new LineData(dataSets);
        line.setData(lineData);
        //折线图背景
        line.setBackgroundColor(0x00000000);   //背景颜色
        line.getXAxis().setDrawGridLines(false);  //是否绘制X轴上的网格线（背景里面的竖线）
        line.getAxisLeft().setDrawGridLines(false);  //是否绘制Y轴上的网格线（背景里面的横线）

        //对于右下角一串字母的操作
        line.getDescription().setEnabled(false);                  //是否显示右下角描述
        line.getDescription().setText("这是修改那串英文的方法");    //修改右下角字母的显示
        line.getDescription().setTextSize(20);                    //字体大小
        line.getDescription().setTextColor(Color.RED);             //字体颜色

        //图例
        Legend legend=line.getLegend();
        legend.setEnabled(true);    //是否显示图例
        legend.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER);    //图例的位置

        //允许缩放和拖动
        line.setDragEnabled(true);
        line.setScaleEnabled(true);
        //X轴
        XAxis xAxis=line.getXAxis();
        xAxis.setDrawGridLines(true);  //是否绘制X轴上的网格线（背景里面的竖线）
        xAxis.setAxisLineColor(Color.WHITE);   //X轴颜色
        xAxis.setAxisLineWidth(1);           //X轴粗细
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);        //X轴所在位置   默认为上面
        xAxis.setValueFormatter(new IAxisValueFormatter() {   //X轴自定义坐标
            @Override
            public String getFormattedValue(float v, AxisBase axisBase) {
                for (int i=0;i<max_x+1;i+=10){
                    if (i==v){
                        return String.valueOf(i);
                    }
                }
                return "";//注意这里需要改成 ""
            }
        });
        xAxis.setAxisMaximum(max_x);   //X轴最大数可以按照最大值显示
        xAxis.setAxisMinimum(min_x);   //X轴最小数值
        //X轴坐标的个数    第二个参数一般填false     true表示强制设置标签数 可能会导致X轴坐标显示不全等问题
        xAxis.setLabelCount(_id+1,false);

        //Y轴
        YAxis AxisLeft=line.getAxisLeft();
        AxisLeft.setDrawGridLines(true);  //是否绘制Y轴上的网格线（背景里面的横线）
        AxisLeft.setAxisLineColor(Color.WHITE);  //Y轴颜色
        AxisLeft.setAxisLineWidth(1);           //Y轴粗细
        AxisLeft.setValueFormatter(new IAxisValueFormatter() {  //Y轴自定义坐标
            @Override
            public String getFormattedValue(float v, AxisBase axisBase) {
                for (int i=0;i<max_y+1;i+=10){
                    if (i==v){
                        return String.valueOf(i);
                    }
                }
                return "";
            }
        });
        AxisLeft.setAxisMaximum(max_y);   //Y轴最大数值
        AxisLeft.setAxisMinimum(min_y);   //Y轴最小数值
        //Y轴坐标的个数    第二个参数一般填false     true表示强制设置标签数 可能会导致X轴坐标显示不全等问题
        AxisLeft.setLabelCount(_id+1,false);
        //是否隐藏右边的Y轴（不设置的话有两条Y轴 同理可以隐藏左边的Y轴）
        line.getAxisRight().setEnabled(false);

        //折线
        //设置折线的式样   这个是圆滑的曲线（有好几种自己试试）     默认是直线
        lineDataSet.setMode(LineDataSet.Mode.LINEAR);
        lineDataSet.setColor(Color.BLUE);  //折线的颜色
        lineDataSet.setLineWidth(0);        //折线的粗细
        //是否画折线点上的空心圆  false表示直接画成实心圆
        lineDataSet.setDrawCircleHole(false);
        lineDataSet.setCircleHoleRadius(3);  //空心圆的圆心半径
        //圆点的颜色     可以实现超过某个值定义成某个颜色的功能   这里先不讲 后面单独写一篇
        lineDataSet.setCircleColor(Color.BLUE);
        lineDataSet.setCircleRadius(3);      //圆点的半径
        //定义折线上的数据显示    可以实现加单位    以及显示整数（默认是显示小数）
        lineDataSet.setValueFormatter(new IValueFormatter() {
            @Override
            public String getFormattedValue(float v, Entry entry, int i, ViewPortHandler viewPortHandler) {
                if (entry.getY()==v){
                    return v+"";
                }
                return "";
            }
        });
    }

    /*
    按钮响应函数归类
     */
    public void set_on(){
        /*
        添加点入数据库并绘制
         */
        bt_add_point.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("Range")
            @Override
            public void onClick(View v) {
                if ((!(et_x.getText().toString().equals("")))&&!(et_y.getText().toString().equals(""))){
                    float x=Float.parseFloat(et_x.getText().toString());
                    float y=Float.parseFloat(et_y.getText().toString());
                    list.add(new Entry(x,y));
                    sort();
                    /*
                    实时更新图表操作
                     */
                    LineDataSet lineDataSet=new LineDataSet(list,"数据点");
                    LineData lineData=new LineData(lineDataSet);
                    line.setData(lineData);
                    line.notifyDataSetChanged();
                    line.invalidate();
                    String point_x="";
                    String point_y="";
                    for (int i=1;i<list.size();i++){
                        point_x+="x="+String.valueOf(list.get(i).getX())+"\n";
                        point_y+="y="+String.valueOf(list.get(i).getY())+"\n";
                    }
                    tv_show_point_x.setText(point_x);
                    tv_show_point_y.setText(point_y);
                }
            }
        });
        /*
        清空数据库数据
         */
        bt_delete.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("Range")
            @Override
            public void onClick(View v) {
                list.clear();
                list.add(new Entry(0,0));
                tv_show_point_x.setText("");
                tv_show_point_y.setText("");
                tv_show_data.setText("");
            }
        });
        /*
        绘制拟合直线按键响应
         */

        bt_fit.setOnClickListener(new View.OnClickListener() {
            @SuppressLint({"Range", "SetTextI18n"})
            @Override
            public void onClick(View v) {
                if (list!=null){
                    /*
                    计算线性回归方程的各项数值
                     */
                    float x_sum=0;
                    float y_sum=0;
                    float x_y_sum=0;
                    float x_x_sum=0;
                    float x_average=0;
                    float y_average=0;
                    float b=0;
                    float a=0;
                    int size=list.size()-1;
                    for(int i=1;i<list.size();i++){
                        x_sum+=list.get(i).getX();
                        y_sum+=list.get(i).getY();
                        x_y_sum+=list.get(i).getX()*list.get(i).getY();
                        x_x_sum+=list.get(i).getX()*list.get(i).getX();
                    }
                    System.out.println(x_sum);
                    b=(float) (size*x_y_sum-x_sum*y_sum)/(size*x_x_sum-x_sum*x_sum);
                    x_average=(float) x_sum/size;
                    y_average=(float) y_sum/size;
                    a=y_average-b*x_average;
                    tv_show_data.setText("y="+b+"x  "+a);
                    /*
                    拟合
                     */
                    List<Entry> liner=new ArrayList<>();
                    liner.add(new Entry(min_x,a));
                    liner.add(new Entry(max_x,max_x*b+a));
                    LineDataSet lineDataSet=new LineDataSet(liner,"线性回归");
                    try {
                        dataSets.remove(1);
                    }catch (Exception ignored){

                    }
                    dataSets.add(lineDataSet);
                    LineData lineData=new LineData(dataSets);
                    line.setData(lineData);
                    line.notifyDataSetChanged();
                    line.invalidate();
                }

            }
        });
    }
    public void sort(){
        //匿名比较类
        Collections.sort(list,new Comparator<Entry>() {
            @Override
            public int compare(Entry o1, Entry o2) {
                return (int) o1.getX() - (int) o2.getX();
            }
        });
        //list.forEach(System.out::println);
    }
}